const httpStatus = require('http-status');
const ApiError = require('../utils/ApiError');
const catchAsync = require('../utils/catchAsync');
const { BackupSetting, Backup } = require('../models');
const path = require('path');
const fs = require('fs');
const { spawn } = require('child_process');
const moment = require('moment');
const config = require('../config/config');
const backupService = require('../services/backup.service');

/**
 * 获取备份设置
 */
const getBackupSettings = catchAsync(async (req, res) => {
  // 备份设置一般只有一条记录，获取第一条
  let backupSettings = await BackupSetting.findOne({ isDeleted: false });
  
  // 如果不存在，则创建默认设置
  if (!backupSettings) {
    backupSettings = await BackupSetting.create({});
  }
  
  res.send(backupSettings);
});

/**
 * 更新备份设置
 */
const updateBackupSettings = catchAsync(async (req, res) => {
  // 备份设置一般只有一条记录，获取第一条
  let backupSettings = await BackupSetting.findOne({ isDeleted: false });
  
  // 如果不存在，则创建新的记录
  if (!backupSettings) {
    backupSettings = await BackupSetting.create(req.body);
  } else {
    // 如果存在，则更新
    Object.assign(backupSettings, req.body);
    await backupSettings.save();
  }
  
  res.send(backupSettings);
});

/**
 * 获取备份记录
 */
const getBackups = catchAsync(async (req, res) => {
  const { limit = 10, page = 1, startDate, endDate } = req.query;
  const skip = (page - 1) * limit;
  
  let query = { isDeleted: false };
  if (startDate && endDate) {
    query.date = {
      $gte: new Date(startDate),
      $lte: new Date(endDate)
    };
  }
  
  const backups = await Backup.find(query)
    .sort({ date: -1 })
    .skip(skip)
    .limit(parseInt(limit));
  
  const total = await Backup.countDocuments(query);
  
  res.send({
    results: backups,
    page,
    limit: parseInt(limit),
    totalPages: Math.ceil(total / limit),
    totalResults: total,
  });
});

/**
 * 创建手动备份
 */
const createBackup = catchAsync(async (req, res) => {
  try {
    // 使用备份服务执行备份
    const backup = await backupService.executeBackup('manual');
    res.status(httpStatus.CREATED).send(backup);
  } catch (error) {
    throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `创建备份失败: ${error.message}`);
  }
});

/**
 * 删除备份
 */
const deleteBackup = catchAsync(async (req, res) => {
  const backup = await Backup.findOne({ _id: req.params.backupId, isDeleted: false });
  if (!backup) {
    throw new ApiError(httpStatus.NOT_FOUND, '备份记录不存在');
  }
  
  // 逻辑删除备份记录
  backup.isDeleted = true;
  await backup.save();
  
  // 删除物理文件
  const backupFilePath = path.join(__dirname, '../../', backup.filePath);
  if (fs.existsSync(backupFilePath)) {
    fs.unlinkSync(backupFilePath);
  }
  
  res.status(httpStatus.NO_CONTENT).send();
});

/**
 * 恢复备份
 */
const restoreBackup = catchAsync(async (req, res) => {
  const backup = await Backup.findOne({ _id: req.params.backupId, isDeleted: false });
  if (!backup) {
    throw new ApiError(httpStatus.NOT_FOUND, '备份记录不存在');
  }
  
  if (backup.status !== 'success') {
    throw new ApiError(httpStatus.BAD_REQUEST, '只能恢复成功的备份');
  }
  
  try {
    // 获取备份文件路径
    const backupFilePath = path.join(__dirname, '../../', backup.filePath);
    
    // 检查文件是否存在
    if (!fs.existsSync(backupFilePath)) {
      throw new ApiError(httpStatus.NOT_FOUND, '备份文件不存在或已被删除');
    }
    
    // 从配置中获取MongoDB连接信息
    const { url } = config.mongoose;
    
    // 构建mongorestore命令参数
    const mongorestoreArgs = [
      '--uri', url,
      '--gzip',
      '--archive=' + backupFilePath,
      '--drop'  // 恢复前删除现有数据
    ];
    
    // 创建恢复前的备份
    await backupService.executeBackup('pre_restore');
    
    // 执行mongorestore命令
    const mongorestore = spawn('mongorestore', mongorestoreArgs);
    
    let stdoutData = '';
    let stderrData = '';
    
    mongorestore.stdout.on('data', (data) => {
      stdoutData += data.toString();
    });
    
    mongorestore.stderr.on('data', (data) => {
      stderrData += data.toString();
    });
    
    // 恢复是一个异步过程，我们不应该等待它完成
    mongorestore.on('close', (code) => {
      if (code === 0) {
        console.log(`数据库恢复成功: ${backupFilePath}`);
      } else {
        console.error(`数据库恢复失败: ${stderrData}`);
      }
    });
    
    res.send({ message: '备份恢复已开始，请等待系统完成操作' });
  } catch (error) {
    throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `恢复备份失败: ${error.message}`);
  }
});

/**
 * 下载备份文件
 */
const downloadBackup = catchAsync(async (req, res) => {
  const backup = await Backup.findOne({ _id: req.params.backupId, isDeleted: false });
  if (!backup) {
    throw new ApiError(httpStatus.NOT_FOUND, '备份记录不存在');
  }
  
  if (backup.status !== 'success') {
    throw new ApiError(httpStatus.BAD_REQUEST, '只能下载成功的备份');
  }
  
  const backupFilePath = path.join(__dirname, '../../', backup.filePath);
  
  // 检查文件是否存在
  if (!fs.existsSync(backupFilePath)) {
    throw new ApiError(httpStatus.NOT_FOUND, '备份文件不存在或已被删除');
  }
  
  // 设置文件名
  const fileName = path.basename(backup.filePath);
  
  // 发送文件
  res.download(backupFilePath, fileName, (err) => {
    if (err) {
      // 处理下载错误
      console.error('下载备份文件失败:', err);
      // 如果响应已经发送，则不要再尝试发送错误响应
      if (!res.headersSent) {
        res.status(httpStatus.INTERNAL_SERVER_ERROR).send({ message: '下载文件时发生错误' });
      }
    }
  });
});

module.exports = {
  getBackupSettings,
  updateBackupSettings,
  getBackups,
  createBackup,
  deleteBackup,
  restoreBackup,
  downloadBackup,
}; 